import {
  groupCheckedKey,
  findParentIdListById,
  findParentIdListByIdList,
  getAllKeysTree,
} from '@/utils/treeUtils';
import { Form, Tree, theme } from 'antd';
import { useEffect, useState } from 'react';

type FormTreeProps = {
  allowClear?: boolean;
  fieldNames?: { label?: string; value?: string; children?: string };
  checkable?: boolean;
  showLine?: boolean;
  onChange?: (value?: React.Key[]) => void;
  multiple?: boolean;
  selectable?: boolean;
  treeData?: { [key: string]: any }[];
  value?: React.Key[];
  request?: () => Promise<{ [key: string]: any }[]>;
  autoExpandParent?: boolean;
  defaultExpandParent?: boolean;
};

type ProFormTreeProps = {
  name: string;
  label?: string;
  hidden?: boolean;
} & FormTreeProps;

const FormTree: React.FC<FormTreeProps> = ({
  fieldNames = {
    value: 'value',
    label: 'label',
    children: 'children',
  },
  checkable,
  showLine,
  onChange,
  multiple,
  selectable,
  value,
  request,
  autoExpandParent,
  defaultExpandParent,
}) => {
  const [checkedKeys, setCheckedKeys] = useState<{
    checked: React.Key[];
    halfChecked: React.Key[];
  }>({ checked: [], halfChecked: [] });
  const [selectedKeys, setSelectedKeys] = useState<React.Key[]>(selectable ? value || [] : []);
  const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
  const [treeData, setTreeData] = useState<{ [key: string]: any }[]>([]);
  const { useToken } = theme;
  const { token } = useToken();
  useEffect(() => {
    if (!request) {
      return;
    }
    request().then((res) => {
      setTreeData(res);
    });
  }, [request]);
  useEffect(() => {
    if (treeData && value) {
      if (defaultExpandParent && value) {
        const keys = findParentIdListByIdList(treeData, value, fieldNames);
        setExpandedKeys(keys);
      }
      if (checkable && value) {
        setCheckedKeys(groupCheckedKey(treeData, value, fieldNames));
      }
    }
  }, [treeData, value]);
  return (
    <Tree
      fieldNames={{
        key: fieldNames?.value || 'value',
        title: fieldNames?.label || 'label',
        children: fieldNames?.children,
      }}
      rootStyle={{
        border: '1px solid',
        paddingTop: token.paddingXXS,
        paddingBottom: token.paddingXXS,
        borderColor: token.colorBorder,
      }}
      checkStrictly
      multiple={multiple}
      checkable={checkable}
      selectable={!checkable && selectable}
      treeData={treeData}
      showLine={showLine}
      selectedKeys={selectedKeys}
      onSelect={(selectedKeysValue) => {
        setSelectedKeys(selectedKeysValue);
        if (onChange) {
          onChange(selectedKeysValue);
        }
      }}
      checkedKeys={checkedKeys}
      onCheck={(checkedKeysValue, info) => {
        if (!Array.isArray(checkedKeysValue)) {
          const childrenAllKeys = getAllKeysTree(
            info.node[fieldNames.children || 'children'] || [],
            {
              key: fieldNames.value,
              children: fieldNames.children,
            },
          );
          const originalAllKeys = [...checkedKeysValue.checked, ...checkedKeysValue.halfChecked];
          let newAllKeys: React.Key[];
          if (info.checked) {
            // 将所有父级与所有孩子也选中
            const parentKeysList = findParentIdListById(
              treeData,
              info.node[fieldNames.value || 'value'],
              fieldNames,
            );
            newAllKeys = [...originalAllKeys, ...parentKeysList, ...childrenAllKeys];
          } else {
            // 所有孩子去除选中
            newAllKeys = originalAllKeys.filter((key) => !childrenAllKeys.includes(key));
          }
          // 去重复
          newAllKeys = Array.from(new Set(newAllKeys));
          setCheckedKeys(groupCheckedKey(treeData, newAllKeys, fieldNames));
          if (autoExpandParent && treeData) {
            const keys = findParentIdListByIdList(treeData, newAllKeys, fieldNames);
            setExpandedKeys(keys);
          }
          if (onChange) {
            onChange(newAllKeys);
          }
        }
      }}
      expandedKeys={expandedKeys}
      onExpand={(expandedKeysValue) => {
        setExpandedKeys(expandedKeysValue);
      }}
    />
  );
};

const ProFormTree: React.FC<ProFormTreeProps> = ({ name, label, hidden, ...props }) => {
  return (
    <Form.Item name={name} label={label} hidden={hidden}>
      <FormTree {...props} />
    </Form.Item>
  );
};
export default ProFormTree;
